/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package scheduleManager;

import app.Global;
import app.MyCellRenderer;
import entities.EmployeeSchedule;
import entities.TimeSlot;
import java.awt.Component;
import java.awt.Frame;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.Vector;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import lib.multiSpanCellTable.AttributiveCellTableModel;
import lib.multiSpanCellTable.CellSpan;

/**
 *
 * @author yoshi
 */
public class ScheduleManagerAssignEmployee extends AbstractScheduleManager {

    public ScheduleManagerAssignEmployee(long departmentId) {
        this(departmentId, Calendar.getInstance());
    }

    public ScheduleManagerAssignEmployee(long departmentId, Calendar calendar) {
        super(departmentId, calendar, new ScheduleManagerModel(departmentId), new ScheduleManagerController(departmentId), false);

        initModel();
        initTable();
    }

    @Override
    protected void initTable() {
        ArrayList<EmployeeSchedule> schedules = this.getMyModel().getSchedules();
        ArrayList<TimeSlot> timeSlots = this.getMyModel().getTimeSlots();
        SimpleDateFormat df = Global.getDefaultDateFormat();
        Vector vData = new Vector();
        Vector vRow = new Vector();
        Vector vHead = new Vector();
        vHead.add("Date");
        vHead.add("Time slot");
        vHead.add("Username");
        vHead.add("Full name");
        vHead.add("Roll");
        vHead.add("Options");

        int count = 0;
        short dateCount = 0;
        Calendar cal = Calendar.getInstance();
        cal.setTime(calendar.getTime());
        cal.add(Calendar.DAY_OF_WEEK, -cal.get(Calendar.DAY_OF_WEEK) + 1);
        Date currentDate = new Date(cal.getTime().getTime());

        TreeMap<ModelKey, Vector> map = new TreeMap<ModelKey, Vector>();

        for (EmployeeSchedule schedule : schedules) {
            vRow = new Vector();
            vRow.add(df.format(schedule.getDate()));
            vRow.add(schedule.getTimeSlot().toShortFormatString());
            vRow.add(schedule.getEmployee().getUsername());
            vRow.add(schedule.getEmployee().getFullName());
            vRow.add(schedule.getEmployee().getRoll().getName());
            vRow.add(new AssignHeadButtonModel(schedule.getDate(), schedule.getTimeSlot(), schedule));

            map.put(new ModelKey(schedule.getDate(), schedule.getTimeSlot(), schedule.getEmployee().getFullName()), vRow);
        }

        for (int i = 0; i < 7; i++) {
            cal.add(Calendar.DAY_OF_WEEK, 1);
            currentDate = new Date(cal.getTime().getTime());
            for (TimeSlot timeSlot : timeSlots) {
                vRow = new Vector();
                vRow.add(Global.getDefaultDateFormat().format(currentDate));
                vRow.add(timeSlot.toShortFormatString());
                vRow.add("Add employee to this time slot:");
                vRow.add("");
                vRow.add("");
                vRow.add(new AssignHeadButtonModel(currentDate, timeSlot, null));

                map.put(new ModelKey(currentDate, timeSlot, "ZZZ"), vRow);
            }
        }

        // init the vector merge Date and Time slot cells
        Vector vDateMerge = new Vector();
        Vector vDateGroup = new Vector();
        Vector vTimeSlotMerge = new Vector();
        Vector vTimeSlotGroup = new Vector();
        Vector vButtonMerge = new Vector();
        long currentTimeSlot = 0;
        currentDate = new Date(0);
        count = 0;
        for (Entry<ModelKey, Vector> entry : map.entrySet()) {
            ModelKey mk = entry.getKey();
            /* Merge date cells */
            if (!df.format(mk.getDate()).equals(df.format(currentDate))) {
                currentDate = mk.getDate();
                vDateGroup = new Vector();
                vDateMerge.add(vDateGroup);
            }
            vDateGroup.add(count);

            /* Merge time slot cells */
            if (!df.format(mk.getDate()).equals(df.format(currentDate)) || mk.getTs().getId() != currentTimeSlot) {
                currentTimeSlot = mk.getTs().getId();
                vTimeSlotGroup = new Vector();
                vTimeSlotMerge.add(vTimeSlotGroup);
            }
            vTimeSlotGroup.add(count);

            /* Merge button cells*/
            if (mk.getFullname().equals("ZZZ")) {
                vButtonMerge.add(count);
            }

            count++;
        }

        vData = new Vector(map.values());
        AttributiveCellTableModel ml = new AttributiveCellTableModel(vData, vHead);
        final CellSpan cellAtt = (CellSpan) ml.getCellAttribute();
        table.setModel(ml);

        table.getColumnModel().getColumn(0).setCellRenderer(new MyCellRenderer(SwingConstants.CENTER));
        table.getColumnModel().getColumn(1).setCellRenderer(new MyCellRenderer(SwingConstants.CENTER));
        table.getColumnModel().getColumn(2).setCellRenderer(new MyCellRenderer(SwingConstants.RIGHT) {

            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                if (!value.toString().equals("Add employee to this time slot:")) {
                    ((JLabel) component).setHorizontalAlignment(SwingConstants.LEFT);
                }
                return component;
            }
        });
        table.makeButtonColumn(5, new AssignHeadButtonEditor(new JCheckBox(), this), new AssignHeadButtonRenderer());

        for (Object list : vDateMerge) {
            int[] columns = {0};
            Vector v = (Vector) list;
            int[] rows = new int[v.size()];

            short i = 0;
            for (Object row : v) {
                rows[i++] = (Integer) row;
            }
            cellAtt.combine(rows, columns);
        }

        for (Object list : vTimeSlotMerge) {
            int[] columns = {1};
            Vector v = (Vector) list;
            int[] rows = new int[v.size()];

            short i = 0;
            for (Object row : v) {
                rows[i++] = (Integer) row;
            }
            cellAtt.combine(rows, columns);
        }

        int[] rows;
        int[] columns = new int[]{2, 3, 4};
        for (Object obj : vButtonMerge) {
            rows = new int[]{(Integer) obj};
            cellAtt.combine(rows, columns);
        }
    }

    private class ModelKey implements Comparable<ModelKey> {

        private Date date;
        private TimeSlot ts;
        private String fullname;

        public ModelKey(Date date, TimeSlot ts, String fullname) {
            this.date = date;
            this.ts = ts;
            this.fullname = fullname;
        }

        public Date getDate() {
            return date;
        }

        public TimeSlot getTs() {
            return ts;
        }

        public String getFullname() {
            return fullname;
        }

        @Override
        public int compareTo(ModelKey o) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy D");
            String s1 = new StringBuilder(df.format(this.getDate())).append(this.getTs().getId()).append(this.fullname).toString();
            String s2 = new StringBuilder(df.format(o.getDate())).append(o.getTs().getId()).append(o.fullname).toString();

            return s1.compareTo(s2);
        }
    }

    @Override
    protected void initModel() {
        if (!Global.getAuth().isDepartmentHead()) {
            JOptionPane.showMessageDialog(Global.getFrame(), "You can not access here, system exit now");
            System.exit(0);
        } else {
            this.getMyModel().initAssignEmployee(this.calendar);
        }
    }
}
